package com.thinkgem.jeesite.common.utils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.regex.Pattern;

/**
 * 日期工具类
 * 
 * @author fanqinglong
 *
 */
public class TimeUtil {
	public static final String DF_SIMPLE_YM = "yyyyMM";
	public static final String DF_SIMPLE_YMD = "yyyyMMdd";
	public static final String DF_SIMPLE_YMDHMS = "yyyyMMddHHmmss";
	public static final String DF_SIMPLE_YMDHMSMS = "yyyyMMddHHmmssSSS";
	public static final String DF_YMDHMS = "yyyy-MM-dd_HH_mm_ss";
	public static final String DF_ZH_YM = "yyyy-MM";
	public static final String DF_ZH_YMD = "yyyy-MM-dd";
	public static final String DF_ZH_YMD1 = "yyyy/MM/dd";
	public static final String DF_ZH_YMD2 = "yyyy.MM.dd";
	public static final String DF_ZH_HMS = "HH:mm:ss";
	public static final String DF_ZH_YMDHMS = "yyyy-MM-dd HH:mm:ss";
	public static final String DF_ZH_YMDMHS1 = "yyyy/MM/dd HH:mm:ss";
	public static final String DF_ZH_YMDHMS2 = "yyyy.MM.dd HH:mm:ss";
	public static final String DF_ZH_YMDHMS_SSS = "yyyy-MM-dd HH:mm:ss,SSS";
	public static final String DF_ZH_YMDHM = "yyyy-MM-dd HH:mm";
	public static final String DF_ZH_YMDHM1 = "yyyy/MM/dd HH:mm";
	public static final String DF_ZH_YMDHM2 = "yyyy.MM.dd HH:mm";
	public static final String DF_ZHCN_YMD = "yyyy年MM月dd日";
	public static final String DF_ZHCN_YMDHM = "yyyy年MM月dd日HH时mm分";
	public static final String DF_ZHCN_YMDHMS = "yyyy年MM月dd日HH时mm分ss秒";
	public static final String[] COMMON_PATTERNS = { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm",
			"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss",
			"yyyy.MM.dd HH:mm" };

	public static Date stringToDate(String dateString, String dateFormat) throws ParseException {
		return new SimpleDateFormat(dateFormat).parse(dateString);
	}

	public static Date stringToDateYMDHMS(String dateString) throws ParseException {
		return stringToDate(dateString, "yyyy-MM-dd HH:mm:ss");
	}

	public static String dateToString(Date date, String dateFormat) {
		return new SimpleDateFormat(dateFormat).format(date);
	}

	public static String dateToStringYMD(Date date) {
		return dateToString(date, "yyyy-MM-dd");
	}

	public static String dateToStringYMDHMS(Date date) {
		return dateToString(date, "yyyy-MM-dd HH:mm:ss");
	}

	public static String transformFormat(String dateStr, String srcFmt, String targetFmt) throws ParseException {
		if ((null == dateStr) || ("".equals(dateStr))) {
			return "";
		}
		Date d = stringToDate(dateStr, srcFmt);
		return dateToString(d, targetFmt);
	}

	public static Date movDateForYear(Date date, int movNum) {
		GregorianCalendar gcal = new GregorianCalendar();
		gcal.setTime(date);
		gcal.add(1, movNum);
		return gcal.getTime();
	}

	public static Date movDateForMonth(Date date, int movNum) {
		GregorianCalendar gcal = new GregorianCalendar();
		gcal.setTime(date);
		gcal.add(2, movNum);
		return gcal.getTime();
	}

	public static Date movDateForDay(Date date, int movNum) {
		GregorianCalendar gcal = new GregorianCalendar();
		gcal.setTime(date);
		gcal.add(5, movNum);
		return gcal.getTime();
	}

	public static Date movDateForHour(Date date, int movNum) {
		GregorianCalendar gcal = new GregorianCalendar();
		gcal.setTime(date);
		gcal.add(11, movNum);
		return gcal.getTime();
	}

	public static Date movDateForMinute(Date date, int movNum) {
		GregorianCalendar gcal = new GregorianCalendar();
		gcal.setTime(date);
		gcal.add(12, movNum);
		return gcal.getTime();
	}

	public static Date movDateForSecond(Date date, int movNum) {
		GregorianCalendar gcal = new GregorianCalendar();
		gcal.setTime(date);
		gcal.add(13, movNum);
		return gcal.getTime();
	}

	public static long countMilliSeconds(Date beginDate, Date endDate) {
		long ms = beginDate.getTime() - endDate.getTime();
		/*if (ms < 0L) {
			ms = -1L * ms;
		}*/
		return ms;
	}

	public static long countSeconds(Date beginDate, Date endDate) {
		long ms = countMilliSeconds(beginDate, endDate);

		return ms / 1000L;
	}

	public static long countMinutes(Date beginDate, Date endDate) {
		long ms = countSeconds(beginDate, endDate);

		return ms / 60L;
	}

	public static long countHours(Date beginDate, Date endDate) {
		long ms = countMinutes(beginDate, endDate);

		return ms / 60L;
	}

	public static long countDays(Date beginDate, Date endDate) {
		long ms = countHours(beginDate, endDate);

		return ms / 24L;
	}

	public static long countDaysIgnoreTime(Date beginDate, Date endDate) throws ParseException {
		return countDays(stringToDate(dateToString(beginDate, "yyyy-MM-dd"), "yyyy-MM-dd"),
				stringToDate(dateToString(endDate, "yyyy-MM-dd"), "yyyy-MM-dd"));
	}

	public static String parseUseTime(Date begin, Date end) {
		if ((begin != null) && (end != null)) {
			long ms = countMilliSeconds(begin, end);
			return parseUseTime(ms);
		}
		return "";
	}

	public static String parseUseTime(long useTime) {
		long s = 1000L;
		long m = s * 60L;
		long h = m * 60L;
		long d = h * 24L;
		String dd = Long.toString(useTime / d);
		String HH = Long.toString(useTime % d / h);
		String mm = Long.toString(useTime % d % h / m);
		String ss = Long.toString(useTime % d % h % m / s);
		return dd + "天" + HH + "时" + mm + "分" + ss + "秒";
	}

	public static Date parseDate(String strDate, String[] parsePatterns) {
		if (strDate == null) {
			return null;
		}
		try {
			return DateUtils.parseDate(strDate.toString(), parsePatterns);
		} catch (ParseException e) {
		}
		return null;
	}

	public static Date parseDate(String strDate) {
		return parseDate(strDate, COMMON_PATTERNS);
	}

	public static String getNowTime() {
		return getNowString("HH:mm:ss");
	}

	public static String getNowDateTime() {
		return getNowString("yyyy-MM-dd HH:mm:ss");
	}

	public static String getNowDateTimeZhCN() {
		return getNowString("yyyy年MM月dd日HH时mm分ss秒");
	}

	public static String getNowString(String format) {
		return dateToString(getNowDate(), format);
	}

	public static Date getNowDate() {
		return new Date();
	}

	public static int getDateYear(Date d) {
		Calendar cal = Calendar.getInstance(TimeZone.getDefault());
		cal.setTime(d);
		return cal.get(1);
	}

	public static int getDateMonth(Date d) {
		Calendar cal = Calendar.getInstance(TimeZone.getDefault());
		cal.setTime(d);
		return cal.get(2) + 1;
	}

	public static int getDateWeek(Date d) {
		Calendar cal = Calendar.getInstance(TimeZone.getDefault());

		cal.setTime(d);

		int idx = cal.get(7);
		if (idx == 1) {
			idx = 7;
		} else {
			idx--;
		}
		return idx;
	}

	public static int getDateDay(Date d) {
		Calendar cal = Calendar.getInstance(TimeZone.getDefault());
		cal.setTime(d);
		return cal.get(5);
	}

	public static int getDateHour(Date d) {
		Calendar cal = Calendar.getInstance(TimeZone.getDefault());
		cal.setTime(d);
		return cal.get(11);
	}

	public static int getDateMinute(Date d) {
		Calendar cal = Calendar.getInstance(TimeZone.getDefault());
		cal.setTime(d);
		return cal.get(12);
	}

	public static int getDateSecond(Date d) {
		Calendar cal = Calendar.getInstance(TimeZone.getDefault());
		cal.setTime(d);
		return cal.get(13);
	}

	public static long getMicroSec(BigDecimal hours) {
		BigDecimal bd = hours.multiply(new BigDecimal(3600000));
		return bd.longValue();
	}

	public static int getCurentMonthDays() {
		return getMonthDays(getNowDate());
	}

	public static int getMonthDays(Date d) {
		Calendar c = Calendar.getInstance();
		c.setTime(getNowDate());
		return c.getActualMaximum(5);
	}

	public static Date getWeekFirstDay(Date date) {
		GregorianCalendar cal = new GregorianCalendar();
		cal.setTime(date);

		cal.setFirstDayOfWeek(2);

		cal.set(7, 2);

		return cal.getTime();
	}

	public static Date getMonthFirstDay(Date date) {
		GregorianCalendar cal = new GregorianCalendar();
		cal.setTime(date);

		cal.setFirstDayOfWeek(2);

		cal.set(5, 1);

		return cal.getTime();
	}

	public static String getDateFormat(String dataStr) {
		String spDay = "-?";
		String spTime = ":?";
		String sp = "\\s";
		String yyyy = "\\d{4}";
		String MM = "\\d{1,2}";
		String dd = "\\d{1,2}";
		String HH = "\\d{1,2}";
		String mm = "\\d{1,2}";
		String ss = "\\d{1,2}";
		if (Pattern.matches(yyyy + spDay + MM, dataStr)) {
			return "yyyy-MM";
		}
		if (Pattern.matches(yyyy + spDay + MM + spDay + dd, dataStr)) {
			return "yyyy-MM-dd";
		}
		if (Pattern.matches(yyyy + spDay + MM + spDay + dd + sp + HH + spTime + mm, dataStr)) {
			return "yyyy-MM-dd HH:mm";
		}
		if (Pattern.matches(yyyy + spDay + MM + spDay + dd + sp + HH + spTime + mm + spTime + ss, dataStr)) {
			return "yyyy-MM-dd HH:mm:ss";
		}
		if (Pattern.matches(HH + spTime + mm + spTime + ss, dataStr)) {
			return "HH:mm:ss";
		}
		if (Pattern.matches(HH + spTime + mm, dataStr)) {
			return "HH:mm";
		}
		return null;
	}

	public static Date getZeroOfDay(Date date) {
		long zero = date.getTime() / 86400000L * 86400000L - TimeZone.getDefault().getRawOffset();

		return new Date(zero);
	}

	public static Date getLastMillisecondsOfDay(Date date) {
		Date zero = getZeroOfDay(date);

		long last = zero.getTime() + 86399999L;

		return new Date(last);
	}

	public static String getMonthName_EN(int idx) {
		String[] names = { "January", "February", "March", "April", "May", "June", "July", "August", "September",
				"October", "November", "December" };
		return names[(idx - 1)];
	}

	public static String getMonthName_ZHCN(int idx) {
		String[] names = { "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月" };
		return names[(idx - 1)];
	}

	public static String getWeekName_EN(int idx) {
		String[] names = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
		return names[(idx - 1)];
	}

	public static String getWeekName_ZHCN(int idx) {
		String[] names = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天" };
		return names[(idx - 1)];
	}

	public static List convertListDateToString(List<Map<String, Object>> list, String dateFormat) {
		if (list == null) {
			return new ArrayList();
		}
		if ((dateFormat == null) || ("".equals(dateFormat))) {
			dateFormat = "yyyy-MM-dd HH:mm:ss";
		}
		for (int i = 0; i < list.size(); i++) {
			Map<String, Object> row = (Map) list.get(i);
			for (Map.Entry<String, Object> col : row.entrySet()) {
				if ((col.getValue() instanceof Date)) {
					String dateStr = dateToString((Date) col.getValue(), dateFormat);
					col.setValue(dateStr);
				}
			}
		}
		return list;
	}

	public static void main(String[] args) {
		Date now = getNowDate();

		System.out.println("今天星期几：" + getDateWeek(now));
		System.out.println("今天星期几：" + getWeekName_EN(getDateWeek(now)));
		System.out.println("今天星期几：" + getWeekName_ZHCN(getDateWeek(now)));

		System.out.println("now=" + dateToStringYMDHMS(now));

		System.out.println("yesterday=" + dateToStringYMDHMS(movDateForDay(now, -1)));

		System.out.println("First of Week=" + dateToStringYMDHMS(getWeekFirstDay(now)));

		System.out.println("First of Month=" + dateToStringYMDHMS(getMonthFirstDay(now)));

		System.out.println(dateToString(getZeroOfDay(now), "yyyy-MM-dd HH:mm:ss,SSS"));

		System.out.println(dateToString(getLastMillisecondsOfDay(now), "yyyy-MM-dd HH:mm:ss,SSS"));
	}
}
